#ifndef __CONNECTION_H
#define __CONNECTION_H
#include <mysql/mysql.h>

class Connection{
public:
	Connection();
	~Connection();
	MYRES * query(const char * sql);
	int connect(const char * host,
				const char * username,
				const char * password,
				const char * db,
				unsigned int port);
	int update(const char * sql);
private:
	MYSQL conn;
};



class ConnectPool{
public:
	static ConnectPool * getInstance(){
		static ConnectPool * pool;
		return &pool;
	}
	
	std::share_ptr<Connection> getConnection();
private:
	ConnectPool();
	~ConnectPool();
	bool loadConfigFile();
	void produceConnTask();
private:
	std::string fname;
	std::string host;
	std::string username;
	std::string password;
	std::string db;
	size_t port;
	std::queue<Connection *> m_queue;
	std::mutex m_mutex;
	std::condition_variable m_cond;
	size_t max_conn_num;
	size_t min_conn_num;
	size_t curr_conn_num;
	std::atomic active_num;
};

class ThreadPool {
	explicit ThreadPool(size_t threadNum = 4) :pool(std::make_share_prt<Pool>()){
		for(int i = 0; i < threadNum; i++){
			std::thread([pool = pool]{
				std::unique_lock<std::mutex> lock(p->mutex);
				for(;;){
					if(!pool->tasks.empty()){
						auto task = std::move(pool->tasks.front());
						pool->tasks.pop();
						lock.unlock();
						task();
						lock.lock();
					}
					else if
				}
			}).detach();
		}
	}
	~ThreadPool(){

	}
	template<typename F>
	void addTask(F && task){
		{
			std::lock_guard<std::mutex> lock(p->mutex);
			pool->tasks.emplace(std::forward<F>(task));
		}
	}
private:
	struct Pool{
		std::mutex mutex;
		std::condition_variable cond;
		std::queue<std::function<void()> > task;
	};

	std::share_ptr<Pool> pool;
};








#include <atomic>
#include <memory>

template<typename T>
class LockFreeQueus{
public:
	LockFreeQueus(){
		Node * node = new Node();
		head.store(node);
		tail.store(node);
	}
	~LockFreeQueus(){
		while(Node * curr = head.load()){
			head.store(curr->next);
			delete curr;
		}
	}
	void push(T val){
		std::share_ptr<T> data(std::make_shared<T>(std::move(val)));
		Node * node = new Node();
		Node * const old_tail = tail.load();
		old_tail->data.swap(node);
		old_tail->next = node;
		tail.store(node);
	}

	std::share_ptr<T> pop(){
		Node * node = pop_head();
		if(!node){
			return std::share_ptr<T>();
		}
		std::share_ptr<T> const res (node->data);
		delete node;
		return res;
	}
private:
	Node * pop_head(){
		Node * const old_head = head.load();
		if(old_tail == tail.load()){
			return nullptr;
		}
		head.store(old_tail->next);
		return old_tail;
	}
private:
	struct Node{
		std::share_ptr<T> data;
		Node * next;
		Node():next(nullptr){}
	}
private:
	std::atomic<Node *> head;
	std::atomic<Node *> tail;
}















#endif